package com.example.pdf;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;

public class PdfUtil {
	/**
	 * 根据关键字和pdf文件字节，全文搜索关键字
	 * 
	 * @param bytes   pdf字节
	 * @param keyword 关键字
	 * @return
	 * @throws Exception
	 */
	private static List<MatchItem> matchAll(byte[] bytes, String keyword) throws Exception {
		List<MatchItem> items = new ArrayList<>();
		PdfReader reader = new PdfReader(bytes);
		// 获取pdf页数
		int pageSize = reader.getNumberOfPages();
		// 逐页匹配关键字
		for (int page = 1; page <= pageSize; page++) {
			items.addAll(matchPage(reader, page, keyword));
		}
		return items;
	}

	/**
	 * 根据关键字、文档路径、pdf页数寻找特定的文件内容
	 * 
	 * @param reader
	 * @param pageNumber 页数
	 * @param keyword    关键字
	 * @return
	 * @throws Exception
	 */
	private static List<MatchItem> matchPage(PdfReader reader, Integer pageNumber, String keyword) throws Exception {
		PdfReaderContentParser parse = new PdfReaderContentParser(reader);
		Rectangle rectangle = reader.getPageSize(pageNumber);
		// 匹配监听
		KeyWordPositionListener renderListener = new KeyWordPositionListener();
		renderListener.setKeyword(keyword);
		renderListener.setPageNumber(pageNumber);
		renderListener.setCurPageSize(rectangle);
		parse.processContent(pageNumber, renderListener);
		return findKeywordItems(renderListener, keyword);
	}

	/**
	 * 找到匹配的关键词块
	 * 
	 * @param renderListener
	 * @param keyword
	 * @return
	 */
	private static List<MatchItem> findKeywordItems(KeyWordPositionListener renderListener, String keyword) {
		// 先判断本页中是否存在关键词
		List<MatchItem> allItems = renderListener.getAllItems();// 所有块LIST
		StringBuffer sbtemp = new StringBuffer("");

		for (MatchItem item : allItems) {// 将一页中所有的块内容连接起来组成一个字符串。
			sbtemp.append(item.getContent());
		}

		List<MatchItem> matches = renderListener.getMatches();

		// 一页组成的字符串没有关键词，直接return
		// 第一种情况：关键词与块内容完全匹配的项,直接返回
		if (sbtemp.toString().indexOf(keyword) == -1 || matches.size() > 0) {
			return matches;
		}
		// 第二种情况：多个块内容拼成一个关键词，则一个一个来匹配，组装成一个关键词
		sbtemp = new StringBuffer("");
		List<MatchItem> tempItems = new ArrayList();
		for (MatchItem item : allItems) {
			if (keyword.indexOf(item.getContent()) != -1) {
				tempItems.add(item);
				sbtemp.append(item.getContent());

				if (keyword.indexOf(sbtemp.toString()) == -1) {// 如果暂存的字符串和关键词 不再匹配时
					sbtemp = new StringBuffer(item.getContent());
					tempItems.clear();
					tempItems.add(item);
				}

				if (sbtemp.toString().equalsIgnoreCase(keyword)) {// 暂存的字符串正好匹配到关键词时
					matches.add(tempItems.get(0));// 得到匹配的项
					sbtemp = new StringBuffer("");// 清空暂存的字符串
					tempItems.clear();// 清空暂存的LIST
					continue;// 继续查找
				}
			} else {// 如果找不到则清空
				sbtemp = new StringBuffer("");
				tempItems.clear();
			}
		}
		return matches;
	}

	/**
	 * 替换目标文字，生成新的pdf文件
	 * 
	 * @param bytes        目标pdf
	 * @param outputStream
	 * @throws Exception
	 */
	private static void manipulatePdf(byte[] bytes, OutputStream outputStream, List<MatchItem> matchItems,
			String keyWord, String keyWordNew) throws Exception {
		PdfReader reader = new PdfReader(bytes);
		PdfStamper stamper = new PdfStamper(reader, outputStream);
		PdfContentByte canvas;
		Map<Integer, List<MatchItem>> mapItem = new HashMap<>();
		List<MatchItem> itemList;
		for (MatchItem item : matchItems) {
			Integer pageNum = item.getPageNum();
			if (mapItem.containsKey(pageNum)) {
				itemList = mapItem.get(pageNum);
				itemList.add(item);
				mapItem.put(pageNum, itemList);
			} else {
				itemList = new ArrayList<>();
				itemList.add(item);
				mapItem.put(pageNum, itemList);
			}
		}
		// 遍历每一页去修改
		for (Integer page : mapItem.keySet()) {
			List<MatchItem> items = mapItem.get(page);
			// 遍历每一页中的匹配项
			for (MatchItem item : items) {
				canvas = stamper.getOverContent(page);
				float x = item.getX();
				float y = item.getY();
				float fontWidth = item.getFontWidth();
				float fontHeight = item.getFontHeight();
				canvas.saveState();
				canvas.setColorFill(BaseColor.WHITE);
				canvas.rectangle(x, y, fontWidth * keyWord.length(), fontWidth + 2);
				canvas.fill();
				canvas.restoreState();
				// 开始写入文本
				canvas.beginText();
				BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
				Font font = new Font(bf, fontWidth, Font.BOLD);
				// 设置字体和大小
				canvas.setFontAndSize(font.getBaseFont(), fontWidth);
				// 设置字体的输出位置
				canvas.setTextMatrix(x, y + fontWidth / 10 + 0.5f);
				// 要输出的text
				canvas.showText(keyWordNew);

				canvas.endText();
			}
		}
		stamper.close();
		reader.close();
	}

	/**
	 * 替换pdf中指定文字
	 * 
	 * @param srcBytes     目标pdf
	 * @param outputStream 新pdf
	 * @param keyWord      替换的文字
	 * @param keyWordNew   替换后的文字
	 * @throws Exception
	 */
	public static void pdfReplace(byte[] srcBytes, OutputStream outputStream, String keyWord, String keyWordNew)
			throws Exception {
		manipulatePdf(srcBytes, outputStream, matchAll(srcBytes, keyWord), keyWord, keyWordNew);
	}
}
